#include "app_serial.h"
#include "app_bluetooth.h"
#include "thirdparty/log.c/log.h"

#include <unistd.h>

int app_serial_init(SerialDevice *serial_device, char *filename)
{
    // 声明串口配置选项结构体
    struct termios options;
    serial_device->super.device_type = SERIAL;
    // 初始化 父设备
    app_device_init(&serial_device->super, filename);
    // 初始化 自己的属性
    // 获取自己的属性
    tcgetattr(serial_device->super.fd, &options);

    // 设置波特率
    cfsetispeed(&options, Baud9600);
    cfsetospeed(&options, Baud9600);

    // 设置数据位
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    // 设置停止位
    options.c_cflag &= ~CSTOPB;
    serial_device->stop_bits = ONE;

    // 设置校验位
    options.c_cflag &= ~PARENB;
    serial_device->parity = NONE;

    // 设置二进制串口
    cfmakeraw(&options);
    options.c_cc[VMIN] = 1;
    options.c_cc[VTIME] = 0;

    // 将设置设置回串口
    tcsetattr(serial_device->super.fd, TCSAFLUSH, &options);
    // 刷新串口
    tcflush(serial_device->super.fd, TCIOFLUSH);

    return 0;
}

int app_serial_setBaudRate(SerialDevice *serial_device, BaudRate baud_rate)
{
    // 设置波特率
    struct termios options;
    if (tcgetattr(serial_device->super.fd, &options) < 0)
    {
        goto BAUD_ERROR;
    }

    // 设置波特率
    if (cfsetispeed(&options, baud_rate) < 0)
    {
        goto BAUD_ERROR;
    }
    if (cfsetospeed(&options, baud_rate) < 0)
    {
        goto BAUD_ERROR;
    }
    // 将设置设置回串口
    if (tcsetattr(serial_device->super.fd, TCSAFLUSH, &options) < 0)
    {
        goto BAUD_ERROR;
    }
    // 刷新串口
    if (tcflush(serial_device->super.fd, TCIOFLUSH) < 0)
    {
        goto BAUD_ERROR;
    }

    return 0;
BAUD_ERROR:
    log_warn("Baud Set error");
    return -1;
}

int app_serial_setConnectionType(SerialDevice *serial_device, ConnectionType connection_type)
{
    switch (connection_type)
    {
    case BLUETOOTH:
        serial_device->super.connection_type = BLUETOOTH;
        // 先用9600波特率和蓝牙芯片握手
        if (app_serial_setBaudRate(serial_device, Baud9600) < 0)
        {
            goto CONNECTION_TYPE_ERROR;
        }
        // 设置为非阻塞模式
        if (app_serial_setBlockMode(serial_device, 0) < 0)
        {
            goto CONNECTION_TYPE_ERROR;
        }
        if (app_bluetooth_exists(&serial_device->super) == 0)
        {
            // 如果成功，设置蓝牙波特率为115200
            if (app_bluetooth_setBaudRate(&serial_device->super, BLUETOOTH_BAUD_115200) < 0)
            {
                goto CONNECTION_TYPE_ERROR;
            }
            // 重置蓝牙芯片
            if (app_bluetooth_reset(&serial_device->super) < 0)
            {
                goto CONNECTION_TYPE_ERROR;
            }
        }
        // 直接用115200通信
        if (app_serial_setBaudRate(serial_device, Baud115200) < 0)
        {
            goto CONNECTION_TYPE_ERROR;
        }
        if (app_bluetooth_setNetId(&serial_device->super, "1111") < 0)
        {
            goto CONNECTION_TYPE_ERROR;
        }
        if (app_serial_setBlockMode(serial_device, 1) < 0)
        {
            goto CONNECTION_TYPE_ERROR;
        }
        // 设置一下蓝牙兼容层的数据转换方法
        serial_device->super.vptr->post_recv = app_bluetooth_postRecv;
        serial_device->super.vptr->pre_send = app_bluetooth_preSend;
        break;
    case LORA:
    default:
        break;
    }
    return 0;
CONNECTION_TYPE_ERROR:
    log_warn("Connection Type Set error");
    return -1;
}

int app_serial_setBlockMode(SerialDevice *serial_device, int mode)
{
    // 设置波特率
    struct termios options;
    if (tcgetattr(serial_device->super.fd, &options) < 0)
    {
        goto BLOCK_MODE_ERROR;
    }

    if (mode)
    {
        // 阻塞模式
        options.c_cc[VMIN] = 1;
        options.c_cc[VTIME] = 0;
    }
    else
    {
        options.c_cc[VMIN] = 0;
        options.c_cc[VTIME] = 5;
    }

    // 将设置设置回串口
    if (tcsetattr(serial_device->super.fd, TCSAFLUSH, &options) < 0)
    {
        goto BLOCK_MODE_ERROR;
    }
    // 刷新串口
    if (tcflush(serial_device->super.fd, TCIOFLUSH) < 0)
    {
        goto BLOCK_MODE_ERROR;
    }

    return 0;
BLOCK_MODE_ERROR:
    log_warn("Block Mode Set error");
    return -1;
}
